package cate.game.train.rune;

import cate.common.table.d.*;
import cate.common.table.fight.skill.row.SkillBaseRow;
import cate.common.table.item.RuneItemLevelUpRow;
import cate.common.table.item.rune.row.*;
import cate.common.util.GameResult;
import cate.common.util.random.RWList;
import cate.game.GameBody;
import cate.game.chat.ChatContentParam;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.RoleEventPublisher;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.event.rune.RuneForgeFailedEvent;
import cate.game.event.rune.RuneForgeSuccessEvent;
import cate.game.notice.msg.NoticeDialogResp;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.role.bag.rune.ReCastTemp;
import cate.game.role.bag.rune.Rune;
import cate.game.train.rune.msg.*;
import easy.java.dev.note.NoteClass;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

@NoteClass(value = "徽章处理")
public class TrainRuneHandler implements RoleEventPublisher {

    public void lock(Role role, String uid, String heroUid, byte pos, boolean lock){
        Rune rune = getRune(role, uid, heroUid, pos);
        if (rune == null) {
            role.getGame().notice.message(role, "徽章不存在");
            return;
        }
        rune.lock = lock;
        role.getGame().notice.message(role, lock ? "徽章锁定成功" : "徽章解锁成功");
        role.sendNow(new RuneLockResp(uid, heroUid, pos, lock));
    }

    /** 玺印分解 */
    public void decompose(Role role, List<String> runeUids) {
        if(runeUids.isEmpty()){
            role.getGame().notice.message(role, "徽章id不可为空");
            return;
        }
        MixRes reward = new MixRes();
        MergeMsgSender sender = new MergeMsgSender();
        for(String runeUid : runeUids){
            Rune rune = role.getBag().rune.getItem(runeUid);
            if (rune == null) {
                role.getGame().notice.message(role, "徽章不存在");
                continue;
            }
            if(rune.lock){
                role.getGame().notice.message(role, "徽章已被锁定，无法分解");
                continue;
            }
            // 如果没有配置分解奖励 就默认为不能分解
            String rewardStr = rune.getTpl(role.getGame()).decomposeStr;
            if (StringUtils.isBlank(rewardStr)) {
                role.getGame().notice.message(role, "该徽章不可分解");
                continue;
            }
            MixRes treward = new MixRes(rewardStr);
            GameResult<Void> r = treward.addCheck(role);
            if (!r.ok()) {
                role.getGame().notice.message(role, r.message);
                continue;
            }
            // 分解符文
            GameResult<RewardShow> removeRes = role.getBag().rune.removeItem(runeUid, sender);
            // 发奖励
            if (!removeRes.ok()) {
                role.getGame().notice.message(role, removeRes.message);
                continue;
            }
            reward.addList(treward);
        }
        sender.send(role, true);
        reward.add(role);
        role.getGame().notice.dialogReward(role, reward);
    }

    /** 玺印重铸 */
    public GameResult<Void> reforge(Role role,
                                    String runeUid,
                                    String heroUid,
                                    byte pos,
                                    byte type,
                                    boolean useLuckyItem,
                                    boolean useLuckyItem2,
                                    List<Integer> skillIds,
                                    List<Integer> chooseAttrs,
                                    List<Integer> chooseGradeAttrs) {
        GameResult<Void> r = new GameResult<>();
        Rune rune = getRune(role, runeUid, heroUid, pos);
        if (rune == null) {
            return r.fail("徽章不存在");
        }
        RuneBaseRow row = rune.getTpl(role.getGame());
        if (row == null || !row.recastType.contains(type)) {
            return r.fail("徽章重铸方式有误");
        }
        MixRes itemRes = null;
        if (CollectionUtils.isNotEmpty(skillIds)) {
            itemRes = new MixRes(row.chooseSkillItemStr);
            GameResult<MixResItem> customizedItemRes = itemRes.consumeCheck(role);
            if (!customizedItemRes.ok()) {
                role.getGame().notice.tipResItem(role, customizedItemRes.data);
                return r.fail(customizedItemRes.message);
            }
        }
        // 判断是否使用幸运重铸道具
        if (useLuckyItem) {
            itemRes = new MixRes(row.luckyReforgeItemStr);
            GameResult<MixResItem> luckyItemRes = itemRes.consumeCheck(role);
            if (!luckyItemRes.ok()) {
                role.getGame().notice.tipResItem(role, luckyItemRes.data);
                return r.fail(luckyItemRes.message);
            }
        }
        if (useLuckyItem2) {
            itemRes = new MixRes(row.niubiRecastItemStr);
            GameResult<MixResItem> luckyItemRes = itemRes.consumeCheck(role);
            if (!luckyItemRes.ok()) {
                role.getGame().notice.tipResItem(role, luckyItemRes.data);
                return r.fail(luckyItemRes.message);
            }
        }
        if (CollectionUtils.isNotEmpty(chooseAttrs)) {
            itemRes = new MixRes(row.chooseAttrItemStr);
            GameResult<MixResItem> customizedItemRes = itemRes.consumeCheck(role);
            if (!customizedItemRes.ok()) {
                role.getGame().notice.tipResItem(role, customizedItemRes.data);
                return r.fail(customizedItemRes.message);
            }
        }
        if (CollectionUtils.isNotEmpty(chooseGradeAttrs)) {
            itemRes = new MixRes(row.chooseGradeAttrItemStr);
            GameResult<MixResItem> customizedItemRes = itemRes.consumeCheck(role);
            if (!customizedItemRes.ok()) {
                role.getGame().notice.tipResItem(role, customizedItemRes.data);
                return r.fail(customizedItemRes.message);
            }
        }
        // 根据重铸类型和活动解析本次的消耗
        MixRes consume;
        int specialType = 0;
        switch (type) {
            case GDRune.RecastType.BASE:
                consume = new MixRes(row.recastStr);
                break;
            case GDRune.RecastType.SKILL:
                consume = new MixRes(row.skillRecastStr);
                break;
            case GDRune.RecastType.ATTR:
                consume = new MixRes(row.attrRecastStr);
                break;
            case GDRune.RecastType.LEVEL_ATTR:
                consume = new MixRes(row.gradeAttrRecastStr);
                break;
            case GDRune.RecastType.SPECIAL_SKILL:
                RuneRecastSkillTypeRow skillTypeRow = role.getGame().table.rune.specialRecast.find(rune.buildSkillLevel(role.getGame()));
                if (skillTypeRow == null) {
                    return r.fail("徽章重铸方式有误");
                }
                consume = new MixRes(skillTypeRow.consumeStr);
                specialType = skillTypeRow.id;
                break;
            default:
                return r.fail("未知的徽章重铸类型!");
        }
        double ratio = 1;
        if (ratio > 0 && ratio < 1) {
            consume.itemMultiply(GDObj.Type.NUM, GDObj.Num.M0, ratio);
        }
        // 如果够的话直接消耗
        EcResult<MixResItem> consumeRes = consume.consumeCheck(role, null);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        // 判断是否要重铸技能
        if (GDRune.RecastType.recastSkill(type)) {
            // 判断是否达到幸运技能次数
            if (row.luckyNum > 0) {
                if (useLuckyItem) {
                    List<Integer> luckySkills = rune.genLuckySkill(role.getGame(), new ArrayList<>(), specialType, true, false);
                    if(luckySkills.isEmpty()){
                        return r.fail("徽章技能选择有误");
                    }
                    // 使用石头的话直接消耗
                    rune.reCast.skillIds = luckySkills;
                } else if(useLuckyItem2) {
                    List<Integer> luckySkills = rune.genLuckyDoubleSkill(role.getGame());
                    if(luckySkills.isEmpty()){
                        return r.fail("徽章技能选择有误");
                    }
                    // 使用石头的话直接消耗
                    rune.reCast.skillIds = luckySkills;
                } else if (role.getRes().rune.get(row.luckyRecastTid) >= row.luckyNum) {
                    List<Integer> luckySkills = rune.genLuckySkill(role.getGame(), new ArrayList<>(), specialType, false, false);
                    if(luckySkills.isEmpty()){
                        return r.fail("徽章技能选择有误");
                    }
                    role.getRes().rune.map.put(row.luckyRecastTid, 0);
                    rune.reCast.skillIds = luckySkills;
                } else if (CollectionUtils.isNotEmpty(skillIds)) {
                    List<Integer> luckySkills = rune.genLuckySkill(role.getGame(),skillIds, specialType, false, true);
                    if(luckySkills.isEmpty()){
                        return r.fail("徽章技能选择有误");
                    }
                    // 使用石头的话直接消耗
                    rune.reCast.skillIds.clear();
                    rune.skillIds = luckySkills;
                    //自动升级
                    int times = role.getGame().table.rune.base.getLevelUpTimes(row.quality, rune.tid);
                    if (times > 0) {
                        for (int i=0; i<times; ++i) {
                            rune.levelUpSkill(role.getGame());
                        }
                    }
                    // 重铸次数+1
                    role.getRes().rune.add(row.luckyRecastTid);
                } else{
                    // 没达到就从普通分组抽，重铸次数+1
                    role.getRes().rune.add(row.luckyRecastTid);
                    rune.reCast.skillIds = rune.genSkill(role.getGame(),false, specialType);
                }
            } else {
                // 没有幸运分组的类型从普通分组抽
                rune.reCast.skillIds = rune.genSkill(role.getGame(), false, specialType);
            }
            role.getRes().rune.noticeUpdate();
        }
        consume.consumeDirect(role, null);
        if (itemRes != null) {
            itemRes.consumeDirect(role, null);
        }

        // 判断是否要重铸基础属性
        if (GDRune.RecastType.recastAttr(type)) {
            rune.reCast.attrIds = rune.genAttr(role.getGame(), chooseAttrs);
        } else if (GDRune.RecastType.recastLevelAttr(type)) {
            rune.reCast.gradeAttrIds = rune.genLevelAttr(role.getGame(), chooseGradeAttrs);
        }
        role.sendNow(new RuneRecastResp(rune, heroUid, pos));
        role.getGame().notice.message(role, "徽章重铸成功");
        role.getHistory().action.runeRecast(consume.count(GDObj.Type.PROP, GDRune.RUNE_ESSENCE_ID));
        role.getHistory().action.runeRecastQuality(row.quality);
        return r.success();
    }

    /** 玺印重铸保存 */
    public EcResult<Void> recastSave(Role role, String runeUid, String heroUid, byte pos, byte type) {
        EcResult<Void> r = new EcResult<>();
        Rune rune = getRune(role, runeUid, heroUid, pos);
        if (rune == null) {
            return r.fail("徽章不存在");
        }
        if (!rune.getTpl(role.getGame()).recastType.contains(type)) {
            return r.fail("徽章重铸方式有误");
        }
        rune.saveTemp(type);
        role.sendNow(new RuneRecastResp(rune, heroUid, pos));
        role.getGame().notice.message(role, "重铸保存成功");
        if (heroUid != null) {
            role.getBase().updatePower();
            publishEvent(role, new HeroPowerChangeEvent(
                    role, getHero(role, heroUid)));
        }
        if (GDRune.RecastType.recastSkill(type)) {
            RuneBaseRow row = rune.getTpl(role.getGame());
            if (row.quality == GDProp.Quality.Q4 || row.quality == GDProp.Quality.Q5) {
                List<String> names = new ArrayList<>();
                for (Integer skillId : rune.skillIds) {
                    if (skillId % 10 != 3) {
                        continue;
                    }
                    SkillBaseRow skillBaseRow = role.getGame().table.skill.base.get(skillId);
                    if (skillBaseRow != null) {
                        names.add(skillBaseRow.name);
                    }
                }
                if (names.size() >= 2) {
                    List<ChatContentParam> params = new ArrayList<>();
                    params.add(ChatContentParam.c(role.getBase().name));
                    for (String name : names) {
                        params.add(ChatContentParam.c(name));
                    }
                    role.getGame().notice.lampOnline(role, GDNotice.TextId.RUNE_RECAST, params);
                }
            }
        }
        return r.success();
    }

    private Hero getHero(Role role, String heroUid){
        return role.getBag().hero.getItem(heroUid);
    }

    /** 获取玺印对象，有英雄id从英雄身上取，没有则从背包里取 */
    private Rune getRune(Role role, String runeUid, String heroUid, Byte pos) {
        if (heroUid != null) {
            Hero hero = getHero(role, heroUid);
            if(hero != null){
                Rune rune = hero.runesOn.getPosItem(pos);
                if (StringUtils.equals(runeUid, rune.uid)) {
                    return rune;
                }
            }
        } else {
            return role.getBag().rune.getItem(runeUid);
        }
        return null;
    }

    /** 玺印锻造 */
    public void forge(Role role, int type, List<String> uids) {
        RuneForgeRow forgeRow = role.getGame().table.rune.forge.get(type);
        if (forgeRow == null) {
            role.getGame().notice.message(role, "徽章合成方式有误");
            return;
        }
        if (uids == null || uids.size() != forgeRow.num) {
            role.getGame().notice.message(role, "请重新选择徽章");
            return;
        }

        for (String uid : uids) {
            Rune po = role.getBag().rune.getItem(uid);
            if (po == null || po.tid != forgeRow.type) {
                role.getGame().notice.message(role, "请重新选择徽章");
                return;
            }
            if(po.lock){
                role.getGame().notice.message(role, "徽章已上锁");
                return;
            }
        }
        // 扣除消耗费用
        MixRes consume = new MixRes(forgeRow.consumeStr);
        GameResult<MixResItem> r = consume.consume(role, null);
        if (!r.ok()) {
            role.getGame().notice.tipResItem(role, r.data);
            role.getGame().notice.message(role, r.message);
            return;
        }

        // 移除所选择符文
        MergeMsgSender sender = new MergeMsgSender();
        for (String id : uids) {
            role.getBag().rune.removeItem(id, sender);
        }
        sender.send(role, true);
        role.getRes().rune.addTimes();
        // 合成符文
        if (forgeRow.successRate >= Math.random()) {
            Rune rune = new Rune(role, forgeRow.resultType, 1);
            role.getBag().rune.addItem(rune, null);
            role.sendNow(new RuneForgeResp(rune));
            role.getRes().rune.noticeUpdate();
            runeDialog(role, rune);
            role.getHistory().action.runeForgeQuality(rune);
            publishEvent(role, new RuneForgeSuccessEvent(role, consume,
                    new MixResItem(GDObj.Type.RUNE, forgeRow.resultType, 1)));
        } else {
            // 合成失败添加熔炼值
            role.getRes().rune.meltingNum += forgeRow.value;
            role.getRes().rune.noticeUpdate();
            // 给与符文分解的奖励
            MixRes reward = new MixRes(forgeRow.failRewardStr);
            reward.add(role, true, GDOperation.RUNE_FORGE);
            role.getGame().notice.dialogReward(role, reward);
            role.getGame().notice.message(role, "徽章合成失败，祝福值+"+ forgeRow.value);
            publishEvent(role, new RuneForgeFailedEvent(role, consume, reward, forgeRow.value));
        }
        role.getHistory().action.forgeTrainRune();
    }

    private void forgeLampOnline(Role role, Rune rune){
    }

    private void runeDialog(Role role, Rune rune){
        Map<Byte, List<String>> runeInstance = new HashMap<>();
        runeInstance.put(GDObj.Type.RUNE, new ArrayList<>());
        runeInstance.get(GDObj.Type.RUNE).add(rune.uid);
        role.getGame().notice.dialog(role, NoticeDialogResp.TYPE_REWARD, "恭喜获得", 0, null, runeInstance);
        forgeLampOnline(role, rune);
    }

    /** 获取玺印锻造奖励 */
    public void getReward(Role role) {
        if (role.getRes().rune.meltingNum < GDRune.MELTING_NUM) {
            role.getGame().notice.message(role, "兑换奖励所需的祝福值不足");
            return;
        }
        Rune rune = new Rune(role, GDRune.MELTING_REWARD_TYPE, 1);
        role.getBag().rune.addItem(rune, null);
        role.sendNow(new RuneForgeResp(rune));
        // 熔炼值修改
        role.getRes().rune.meltingNum -= GDRune.MELTING_NUM;
        role.getRes().rune.noticeUpdate();
        runeDialog(role, rune);
    }

    /**
     * 玺印突破
     *
     * <p>用3个龙雀印合成一个真龙印 保留原来的技能 属性进行升级
     */
    public GameResult<Void> runeBreak(Role role, String runeUid, String heroUid, byte pos, List<String> runeList) {
        GameResult<Void> r = new GameResult<>();
        if (runeList == null || runeList.size() != GDRune.BREAK_NUM) {
            return r.fail("徽章突破材料选择有误");
        }
        // 突破时选择的符文本体 需要保留原来的技能
        Rune rune = getRune(role, runeUid, heroUid, pos);
        if (rune == null) {
            return r.fail("徽章突破材料选择有误");
        }
        r = beakAvaible(role,rune);
        if (!r.ok()) {
            return r;
        }
        // 检测用于消耗的材料是否满足条件
        for (String s : runeList) {
            Rune consumeRune = role.getBag().rune.getItem(s);
            r = beakAvaible(role,consumeRune);
            if (!r.ok()) {
                return r;
            }
        }
        // 扣除突破的资源
        EcResult<MixResItem> consumeRes = new MixRes(GDRune.BREAK_CONSUME_STR).consume(role, null);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        for (String s : runeList) {
            role.getBag().rune.removeItem(s, null);
        }
        rune.tid = GDRune.BREAK_TID;
        rune.reCast = new ReCastTemp();
        rune.reCast.initialize();
        rune.levelUpAttr(role.getGame());
        role.sendNow(new RuneBreakResp(rune, heroUid, pos));

        RewardShow rewardShow = new RewardShow();
        rewardShow.addBagInstance(rune);
        role.getGame().notice.dialog(role, rewardShow);

        onUpdatePower(role, heroUid);
        role.getHistory().action.runeBreakToForever();
        breakLampOnline(role, rune.tid);
        return r.success();
    }

    private void breakLampOnline(Role role, int tid){
    }

    private GameResult<Void> beakAvaible(Role role,Rune rune) {
        GameResult<Void> r = new GameResult<>();
        if (rune == null) {
            return r.fail("徽章不存在");
        }
        if (rune.getTpl(role.getGame()) == null) {
            return r.fail("徽章不存在");
        }
        if (rune.getTpl(role.getGame()).id != GDRune.BREAK_REQUIRE_TID) {
            return r.fail("徽章不存在");
        }
        return r.success();
    }

    /** 玺印强化 */
    public GameResult<Void> runeLevelUp(Role role, String runeUid, String heroUid, byte pos, List<String> consumeList, MixRes consume) {
        GameResult<Void> r = new GameResult<>();
        Rune rune = getRune(role, runeUid, heroUid, pos);
        if (rune == null) {
            return r.fail("强化徽章选择有误");
        }
        // 本次升级的总exp
        int exp = 0;
        if (consumeList != null && !consumeList.isEmpty()) {
            for (String s : consumeList) {
                Rune consumeRune = role.getBag().rune.getItem(s);
                if (consumeRune == null) {
                    return r.fail("徽章不存在");
                }
                if (consumeRune.getTpl(role.getGame()).baseExp <= 0) {
                    return r.fail("徽章不可被吞噬");
                }
                if(consumeRune.lock){
                    return r.fail("徽章已上锁");
                }
                exp += consumeRune.getConsumeExp(role.getGame());
            }
        }
        if (consume != null && !consume.isEmpty()) {
            GameResult<MixResItem> consumeRes = consume.consumeCheck(role, null);
            if(!consumeRes.ok()){
                role.getGame().notice.message(role, consumeRes.message);
                return r.fail(consumeRes);
            }
            for (MixResItem item : consume.items) {
                if(item.type != GDObj.Type.PROP){
                    return r.fail("徽章强化石选择有误");
                }
                RuneItemLevelUpRow expRow = role.getGame().table.item.runeLevelUp.get(item.tid);
                if (expRow == null) {
                    return r.fail("徽章强化石选择有误");
                }
                exp += expRow.value * item.num;
            }
        }
        MergeMsgSender sender = new MergeMsgSender();
        if(consumeList != null){
            consumeList.forEach(uid -> role.getBag().rune.removeItem(uid, sender));
        }
        if (consume != null && !consume.isEmpty()) {
            EcResult<MixResItem> consumeRes = consume.consume(role, null, sender);
            if(!consumeRes.ok()){
                role.getGame().notice.tipResItem(role, consumeRes.data);
                return r;
            }
        }
        sender.send(role, true);
        rune.addExp(role.toPlayBuildContext(), exp);
        role.sendNow(new RuneLevelUpResp(rune, heroUid, pos));
        role.getGame().notice.message(role,"徽章强化成功");
        onUpdatePower(role, heroUid);
        return r.success();
    }

    private void onUpdatePower(Role role, String heroUid) {
        if (heroUid != null) {
            role.getBase().updatePower();
            publishEvent(role, new HeroPowerChangeEvent(
                    role, getHero(role, heroUid)));
        }
    }

    public GameResult<Void> gradeUp(Role role, String heroUid, String runeUid, byte pos) {
        GameResult<Void> r = new GameResult<>();
        Rune rune = getRune(role, runeUid, heroUid, pos);
        RuneBaseRow row;
        if (rune == null || (row = rune.getTpl(role.getGame())) == null) {
            return r.fail("徽章选择有误");
        }
        if (row.nextLevelTid == 0) {
            return r.fail("徽章已经最高阶拉");
        }
        RuneBaseRow nextRow = role.getGame().table.rune.base.get(row.nextLevelTid);
        if (nextRow == null) {
            return r.fail("徽章已经最高阶拉");
        }
        if (rune.level < nextRow.levelLimit) {
            return r.fail("强化等级不足");
        }
        GameResult<MixResItem> consumeRes = new MixRes(row.gradeUpConsumeStr).consume(role);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        rune.onGradeUp(role.getGame());
        role.sendNow(new RuneGradeUpResp(heroUid, rune, pos));
        onUpdatePower(role, heroUid);
        return r;
    }

    public GameResult<Void> customRune(Role role, int itemId, List<Integer> skills) {
        GameResult<Void> r = new GameResult<>();
        CustomRuneItemRow itemRow = role.getGame().table.rune.custom.get(itemId);
        if (itemRow == null) {
            return r.fail("道具不存在");
        }
        RuneBaseRow baseRow = role.getGame().table.rune.base.get(itemRow.runeTid);
        if (baseRow == null) {
            return r.fail("道具不存在");
        }
        if(itemRow.random){
            skills = randomSkill(role.getGame(), itemRow.skillGroup, itemRow.skillNum);
        }
        if (skills.size() != itemRow.skillNum) {
            return r.fail("技能选择有误");
        }
        for (Integer skill : skills) {
            boolean exist = role.getGame().table.rune.skill.existSkill(skill, itemRow.skillGroup);
            if (!exist) {
                return r.fail("技能选择有误");
            }
        }
        if (role.getBag().rune.gridEmpty() <= 0) {
            return r.fail("背包已满");
        }
        // 扣道具
        GameResult<RewardShow> removeRes = role.getBag().prop.removeItem(itemId, 1, null);
        if (!removeRes.ok()) {
            return r.fail(removeRes);
        }
        Rune rune = new Rune(role, itemRow.runeTid, 1);
        rune.initialize(role);
        rune.skillIds.clear();
        rune.skillIds.addAll(skills);
        role.getBag().rune.addItem(rune, null);
        RewardShow show = new RewardShow();
        show.addInsRwd(GDObj.Type.RUNE, rune.uid);
        role.getGame().notice.dialog(
                role,
                NoticeDialogResp.TYPE_REWARD,
                "恭喜获得",
                0,
                show.tplRwd,
                show.insRwd);
        return r;
    }

    private List<Integer> randomSkill(GameBody game, int skillGroup,int skillNum){
        List<Integer> skills = new ArrayList<>();
        // 原型技能不能重复
        Set<Integer> protoSet = new HashSet<>();
        for (int i = 0; i < skillNum; i++) {
            RuneSkillRow skillRow = randomSkill(game, skillGroup, protoSet);
            if (skillRow != null) {
                SkillBaseRow base = game.table.skill.base.get(skillRow.skillId);
                protoSet.add(base == null ? skillRow.skillId : base.protoId);
                skills.add(skillRow.skillId);
            }
        }
        return skills;
    }

    /** 根据分组随机抽技能，同时过滤相同原型id的技能 */
    private RuneSkillRow randomSkill(GameBody game, int groupId, Set<Integer> protoIds) {
        RWList<RuneSkillRow> rwl = new RWList<>();
        for (RuneSkillRow row : game.table.rune.skill.getList()) {
            SkillBaseRow base = game.table.skill.base.get(row.skillId);
            int protoId = base == null ? row.skillId : base.protoId;
            if (row.groupId == groupId && !protoIds.contains(protoId)) {
                rwl.add(row);
            }
        }
        rwl.setup();
        return rwl.get();
    }
}
